home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
013
/
sd3.arc
/
SD3.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-06-15
|
60KB
|
1,580 lines
;------------------------------------------------------------------------------;
; ;
; Switch Directory - SD Copyright (c) Stephen M. Falatko, 1987 ;
; ;
; Switch Directory (SD) is a utility that allows easy switching ;
; between subdirectories and drives with a minimum of typing. SD ;
; has been designed to replace the DOS CD command and provide ;
; enhancements to the CD command. SD allows you to specify a ;
; specific subdirectory name, a combination of subdirectory names ;
; and search switches or a complete path specifier. All features of ;
; SD work across disk drives. If you have made a mistake, hitting ;
; Ctrl-Brk while SD is searching will break you out of SD and put ;
; you back in the subdirectory you started in. With version 3.0 SD ;
; will also except a 'minimum match' to a subdirectory name (i.e. if ;
; you have only one directory that begins with 'LO' then SD LO will ;
; take you there even if the full name is LOTUS). Given a full path ;
; designation, SD switches to the specified path without searching. ;
; An important feature of SD is that it can be enqueued to PCED, the ;
; DOS Command EDitor by Chris Dunford (and its public domain ;
; counterpart CED. When enqueued SD will seem like and extension of ;
; DOS. In this configuration SD dos NOT have to be present anywhere ;
; on your disk drives. ;
; ;
; ;
;Usage ;
; ;
; [d:\....]>SD [drive][command specification] ;
; ;
; [drive] - the drive to search. (if not searching the current drive) ;
; ;
; [command specification] ;
; ;
; - this can be any valid CD command or any combination of \ ;
; (for specific paths) or / (for search below the current ;
; dir) (if blank SD returns the current path). ;
; ;
; A valid command could be: ;
; ;
; SD c:\turbo/source\myprog ;
; ;
; This would switch to c:\turbo then search its subdirectories for ;
; a source subdirectory then switch to the myprog subdirectory. ;
; If no \ or / is specified then the entire disk is searched for ;
; the desired subdirectory starting with the current directory. ;
; ;
; Special Command: SD [c will enqueue SD to the CED program (p for PCED) ;
; SD [c+ will enqueue SD without online help. ;
; ;
; ;
; ;
;The source code was originally developed from Vern Buerg's LDIR program and ;
;Charles Wooster's WHISK program. PrintS and GetDir are Copyrighted by there ;
;authors. ;
; ;
;6/04/87 - Stephen Falatko ;
; ;
;Written for the A86 assembler (All numbers with leading 0 are hex) ;
; ;
;------------------------------------------------------------------------------;
;---------------------------------------------------------------------------;
; ;
; Macros and Equates ;
; ;
;---------------------------------------------------------------------------;
LF Equ 10
CR Equ 13
Stopper Equ 255 ;Ends print strings
;
; These equates are for DOS functions. They are all in hex. A86 defaults
; to hex if the number has a leading 0.
;
SetDrive Equ 0E
CurrentDisk Equ 019 ;Get current disk
SetDTA Equ 01A ;Set data transfer area
ChangeDir Equ 03B ;Change directory
GetPath Equ 047 ;Get current directory
Change_Dir MACRO
Mov DX,Offset #1
Mov AH,ChangeDir
Int 021
#EM
Set_Drive MACRO
Mov AH,SetDrive
Int 021
#EM
Get_Path MACRO
Mov AH,GetPath
Int 021
#EM
Current_Disk MACRO
Mov AH,CurrentDisk
Int 021
#EM
;---------------------------------------------------------------------------;
; ;
; Here is where the code begins ;
; ;
;---------------------------------------------------------------------------;
CODE SEGMENT
Org 0100
Main:
Jmp Start
;---------------------------------------------------------------------------;
; ;
; Data Areas, Constants, Etc. ;
; ;
;---------------------------------------------------------------------------;
Version Db CR,'Switch Directory 3.0',CR,LF
Copyright Db 'Copyright (c) 1987 by Stephen M. Falatko',CR,LF
FakeEOF Db 26
Errlvl Db 0 ;DOS return code
;
; These are flags set by the command line processing
;
;
RootFlag Db 0 ; signal indicating default to root (0)
CDFlag Db 0 ; signal of specific path (1)
OneDeepFlag Db 0 ; search only current dir (1)
;
; This flag is set to indicate that a subdirectory has been found (ie if its
; 0 at the end then we did not find the subdirectory)
;
Done_Flag Db 0 ; found subdir during search
;
; This flag is set if SD is enqueued to CED
;
CEDFlag Db 0
;
; If this flag is set then help is available if ? is entered on the
; command line
;
HelpFlag Db 1
;
; These variables hold the systems Ctrl-Break address so we can restore
; it when we exit
;
CtrlBrkOff Dw 0
CtrlBrkSeg Dw 0
;
; Here we will store the desired subdirectory (and drive if selected)
; as well as the original path and drive
;
Sub_Dir Db 63 Dup (0) ; The sub dir we want to change to
ScratchDirStart Db 'x:\' ; This is a scratch area for the
ScratchDir Db 63 Dup (0) ; GetDir function
OrigDr Db 'x:' ; Original drive
OrigDir Db '\',63 Dup (0) ; and path
RootDir Db 'x:\',0 ; To get vol label
Count Dw 0 ; Number of args on command line
;
; These variables are used by the search routine
;
DtaPointer Dw DtaAreaBegin ; Pointer to our DTA area
Direction Db 0 ; Flag to indicate search subdirs
; of the current dir or not
BackOneDir Db '..',0 ; Asciiz 'filename' to backup
; one directory
SearchAsciiZ Db '*.*',0 ; Search filename
;
; Error messages
;
NoHelp Db CR,LF,'ERROR - Installed without help',CR,LF,Stopper
ErrorMsgs Db CR,LF,'Illegal drive specifier - must be A to z',CR,LF,Stopper
Db CR,LF,'Maximum of 64 characters on command line',CR,LF,Stopper
Db CR,LF,'Illegal character on command line ',CR,LF,Stopper
Db CR,LF,'Currently in root directory ',CR,LF,Stopper
Db CR,LF,'Command line contains an invalid path ',CR,LF,Stopper
Db CR,LF,'Subdirectory Not Found ',CR,LF,Stopper
Start:
;
; If we are enqueued as a CED command we must preserve the DS register
; and null out the CED internal command line. (When we leave we don't
; want DOS to do anything)
;
CS Cmp CEDFlag,1 ; Enqueued to CED ?
Jne NoCED
Mov B [SI],CR ; Null out the CED Buffer for our exit
Mov BP,DX ; save pointer to CED internal buffer
Mov ES,DS ; This saves the DS value if we are
; enqueued to CED (points to CED internal
; buffer)
Mov DS,CS ; make sure our data is from this segment
;
; If we are not enqueued to CED then we merely call setup
;
NoCED:
Call SetUP ; Save current drive and path, reset drive
;
; We begin by determining if there are any command line arguments. If we
; are enqueued to CED then we see if the first character in the buffer is a
; carriage return. If we are running from DOS then we look in the PSP for the
; command line count.
;
Cmp CEDFlag,1
Jne Not_Enqueued_To_CED
;
; Nothing but CR on command line? If so show path and leave
;
CED_CR_Check:
ES Mov AL,B [BP] ; Any characters on the command line?
Inc BP
Cmp AL,' '
Je CED_CR_Check
Cmp AL,CR
Je No_Parameters ; no so go set to root and leave
;
; The first character wasn't a CR so let's find out how many characters
; are on the command line and go process them.
;
Mov CX,64 ; assume 64 characters on command line
Mov BX,CX ; save CX in BX
Mov AL,CR ; want to find CR
Mov DI,BP ; point DI to CED command line
Repne Scasb ; scan for CR
Jcxz Too_Many_Characters
Sub BX,CX ; calculate number of chars on command line
Mov CX,BX
Jmp Short Got_Parameters ; go process them
Too_Many_Characters:
Mov Errlvl,2 ; signal error type (too many characters)
Jmp Error_Found
;
; If we are not enqueued to CED we get the number of chars from the PSP
;
Not_Enqueued_To_CED:
Sub CX,CX ; Clear CX
Mov CL,B [080] ; Get the number of characters on the
; command line (from the PSP)
Cmp CX,64 ; more than 64 characters not allowed
Ja Too_Many_Characters
Cmp CX,0 ; Anything on the command line?
Jne Got_Parameters
;
; If we find nothing then we show the current path and leave
;
No_Parameters:
Call ShowPath ; set root dir and leave
Jmp Exit
;
; We have found some parameters so we processes them.
;
Got_Parameters:
Call CommandLine
;
; If the carry flag is set when we exit CommandLine we were unsuccessful
;
Jc Error_Found
;
; If Done_Flag is set then we were successful, we're finished and we can leave
;
Cmp Done_Flag,1
If e Jmp Exit
;
; If we return from CommandLine with CDFlag set that indicates that a
; specific path has been selected and we switch to that specified path.
; Otherwise we search for the desired subdirectory
;
Cmp CDFlag,1
Jne Look_For_The_Subdir
Call SetPath
;
; If the carry flag is set upon return from SetPath the path does not
; exist and we display the not found message and return to the starting point
; otherwise we're through and we can leave
;
If nc Jmp Short Exit
Mov Errlvl,5 ; signal error type (invalid path)
Jmp Short Error_Found
;
; Now if CDFlag was not set we must search for the subdir. We will begin by
; searching the current directory (like the CD command) and then, if required,
; we'll search the rest of the disk.
;
Look_For_The_Subdir:
Mov OneDeepFlag,1 ; search current level
Call GetDir ; Read the directory
;
; Now, we reset OneDeepFlag just in case and see if we were successfull
;
Mov OneDeepFlag,0 ; reset OneDeepFlag
Cmp Done_Flag,1 ; did we find it?
Je Exit ; found it so leave
;
; If we were not successful searching the current directory then we search
; more of the disk. (if rootflag is set then we search the whole disk,
; otherwise we search only the subordinate directories.
;
Cmp RootFlag,1 ; default to the root directory?
If ne Call No_Arg ; if not equal set to root for search
Call GetDir ; Read the directory
;
; If Done_Flag is set then we have been successful, otherwise we did not
; find the desired subdirectory.
;
Cmp Done_Flag,1
Je Exit
Mov Errlvl,6 ; signal error type (subdir not found)
Jmp Short Error_Found
;
; If we make it here we have not found the subdirectory so we tell the user
; and return them to the starting drive:subdirectory.
;
Error_Found:
;
; We begin by sending a message to the user
;
Xor AX,AX ; clear AX
Mov DX,Offset ErrorMsgs ; point to the beginning of the error msgs
Mov AL,Errlvl ; which error?
Dec AX ; decrement for position
Mov CX,45 ; characters per message
Mul CL ; times error type-1
Add DX,AX ; point to it
Call PrintS
;
; Now we reset the drive if it has been changed. NOTE: A Ctrl+Brk during
; processing will come here and the user will be returned home (so to speak)
;
NFCB:
Sub DX,DX ; clear DX
Mov DL,OrigDr ; get original drive
Cmp DL,RootDir ; compare with current drive
;
; If the selected directory does not match the original directory reset
;
Je Same_Drive
Sub DL,'A' ; change DL from ascii
Set_Drive ; Macro...
;
; Now we reset to our original path and leave
;
Same_Drive:
Change_Dir OrigDr ; Set path to original path (Macro...)
Exit:
;
; Now, if we are enqueued to CED we leave with a far return, otherwise
; we exit with DOS function 4C.
;
Cmp CEDFlag,1 ; enqueued to CED
Jne ExitDOS
Mov RootFlag,0 ; reset flags for next time
Mov CDFlag,0
Mov OneDeepFlag,0
Mov Done_Flag,0
Mov DtaPointer,offset DtaAreaBegin ; reset pointer to our DTA
Mov ES,CS ; clear out start of DTA
Mov DI,[DtaPointer]
Mov AX,0
Mov CX,43
Dta_Clear:
Stosw
loop Dta_Clear
;
; During the Setup procedure we took over the Ctrl-Break address
; so now we restore it.
;
Mov DX,CtrlBrkOff ; Ctrl-Break offset
Mov DS,CtrlBrkSeg ; Ctrl-Break segment
Mov AH,025 ; set interrupt vector
Int 021
RetF ; yes, exit with far return
ExitDOS:
Mov AL,Errlvl ; Return to system
Mov AH,04C ; via EXIT
Int 021
;---------------------------------------------------------------------------;
; No_Arg ;
; ;
; No_Arg resets the current path to the root directory. ;
; ;
;---------------------------------------------------------------------------;
No_Arg:
; If no argument then set current
Change_Dir RootDir ; path to root directory
Ret
;---------------------------------------------------------------------------;
; SetUp ;
; ;
; SetUp initializes some variables and resets the disk drives ;
; ;
;---------------------------------------------------------------------------;
SetUp:
Push DX,ES,DS
;
; We begin with a disk reset
;
Mov AH,0D ; Reset diskettes
Int 021
;
; Now we call DOS for the current disk drive and store the information
; as an ascii drive specifier in several variables for future use
;
Current_Disk ; Get current disk (Macro...)
Add AL,'A'
Mov OrigDr,AL ; Save original drive letter
Mov RootDir,AL ;
Mov ScratchDirStart,AL
;
; We also want to store our current path so we can return if necessary
Mov DL,OrigDr ; put original drive in DL
Sub DL,'@' ; convert from ascii character
Mov SI,Offset OrigDir + 1 ; the original drive
Get_Path ; Macro...
;
; Our last task is to point the Ctrl+Break vector to our Not_Found code
; so the user is left where they began if using Ctrl+Break. But first we
; store the current Ctrl-Brk vector so we can restore it when we leave
;
Mov AX,03523 ; call DOS for Ctrl-Break location
Int 021
Mov CtrlBrkSeg,ES
Mov CtrlBrkOff,BX
;
; Now let's set up our Ctrl-Brk.
;
Mov AX,02523 ; set Ctrl+Break vector to point
Mov DX,Offset CtrlBrk ; to our not found. This way a Ctrl+Brk
Int 021 ; will leave us in the place we started
Pop DS,ES,DX
Ret
;---------------------------------------------------------------------------;
; CommandLine ;
; ;
; CommandLine parses the command line, looking for switches and sub- ;
; dir names ;
; ;
;---------------------------------------------------------------------------;
CommandLine:
;
; We begin by setting DI and defaulting SI to the PSP
;
Mov SI,081 ; point SI to the beginning of the
; command line
;
; If we are Enqueued to CED then we want SI to point to BP-1.
;
Cmp CEDFlag,1 ; enqueued to CED
Jne Set_DI ; nope, go on
Dec BP ; decrement BP
Mov SI,BP ; mov BP to SI
;
; Now setup DI
;
Set_DI:
Mov DI,Offset Sub_dir ; point DI to our internal buffer for
; the desired sub directory name
;
; Now, we want to scan the command line to see if a drive was specified
; We do this by looking for a ':' character. (remember cx holds the number
; of parameters)
;
Push DI ; save DI
Mov DI,SI
Mov al,':' ; we'll look for a ':'
Repne Scasb
;
; Just to be sure we found a character and not the end of the line we peek
; at the position immediately before the current DI position
;
ES Cmp B [DI-1],':' ; did we find one or are we at the end
; of the command line? (the segment
; override is needed if enqueued to CED)
Jne Clean_Up ; if we did not find a ':' the go on
;
; If we did find a drive letter then we set SI to point to the char after ':'
;
Mov SI,DI ; now, point SI to the character following
; the ':' character
;
; We now point DI to the drive letter and put it in AL
;
Sub DI,2 ; point DI to the drive specifier
ES Mov AL,B [DI] ; save the drive specifier in al - again
; the segment override is needed for CED)
;
; We must check the drive letter to see that it is a letter and then make sure
; it is capitalized
;
Cmp AL,'A' ; compare with A
If b Jmp DriveError ; if smaller then it is an erroneous drive
Cmp AL,'z' ; compare with z
If a Jmp DriveError ; if larger then it is an erroneous drive
Cmp AL,'a' ; lowercase letter?
Jb New_Drive? ; no its upper case so lets go on
Xor AL,020 ; make upper case
;
; Now we have an uppercase drive letter we first check to see that it is
; different from the original drive if its not we go on.
;
New_Drive?:
Cmp OrigDr,AL
Je Anything_Else_On_CLine?
;
; We have a different drive letter so lets store it and the change drives
;
Mov RootDir,AL ; save new drive specifier
Mov ScratchDirStart,AL
;
; After saving we call DOS and change the drive to the desired one
;
Sub DX,DX ; clear dx
Mov DL,AL ; must change drive to number, not ascii
Sub DL,'A'
Set_Drive ; Macro....
;
; To speed things up we look to see if there's anything but a CR on the
; command line.
;
Anything_Else_On_CLine?:
ES Cmp B [SI],' ' ; strip the spaces (ES override for CED)
Jne Not_Blank ; not a blank, how about a CR?
Inc SI ; increment SI to check the next character
Jmp Short Anything_Else_On_CLine?
Not_Blank:
ES Cmp B [SI],CR ; found a CR?
Jne Clean_Up ; if not go on
Mov Done_Flag,1
Pop DI ; get DI off stack
Jmp ExitCL ; leave
Clean_Up:
Pop DI ; get DI off stack
;
; We've now found a drive if it has been specified and we're ready
; to look at the rest of the command line
;
Parse_Command_Line:
Mov DS,ES ; must play with segments incase enqueued
; to CED
Lodsb ; get character from command line and
; put it in al
Mov DS,CS
Cmp AL,' ' ; strip leading blanks from the command
Jz Parse_Command_Line ; line
Cmp AL,CR ; is it a carriage return ?
If e Jmp We_Are_Finished ; if so we're at the end so jump on
;
; We need to check and see if we are to be enqueued to CED
;
Cmp AL,'[' ; found enqueue command?
Jne Back_One? ; nope, go on
Cmp DI,Offset Sub_Dir ; found it, is it the first character?
If e Jmp CEDEnqueue ; yes then enqueue
Stc ; no, error so leave
Mov Errlvl,3 ; signal error type (illegal character)
Jmp ExitCL
;
; If we find a '.' character we must check for '..' which CD uses
; to go back one level
;
Back_One?:
Cmp AL,'.'
Jne Display_Help?
;
; We found one '.' but are there two?
;
ES Cmp W [SI-1],'..' ; two periods?
Je Go_Back_One ; if so back one dir.
Stc ; if not error
Mov Errlvl,3 ; signal error type (illegal character)
Jmp ExitCL
Go_Back_One:
Change_Dir BackOneDir ; change back one
Jnc Go_Back_One_Worked
Mov Errlvl,4 ; signal error type (in root)
Jmp ExitCL ; leave
Go_Back_One_Worked:
Mov Done_Flag,1 ; else set done_flag and leave
Jmp ExitCL ; do a not so nice jump to exit
;
; If the help character (?) is the first character on the command line
; then we display the help message and leave
;
Display_Help?:
Cmp AL,'?' ; help character?
Jne Search_Below?
Cmp DI,Offset Sub_Dir ; is it the first character ?
Jne Search_Below?
;
; Now that we have found the help character is help available?
;
Cmp HelpFlag,1 ; help info loaded ?
Je Show_Help ; yes so display it
;
; Help not available, display message.
;
Mov DX,Offset NoHelp ; display error message and leave
Call PrintS
Mov Done_Flag,1
Jmp ExitCL
Show_Help:
Mov DX,Offset Help ; yes, let's display the help screen and
Call PrintS ; then leave
Mov Done_Flag,1
Jmp ExitCL
;
; The / switch indicates that we are only to search for subdirectories of
; the current directory. (This was changed in version 3.0 of SD)
;
Search_Below?:
Cmp AL,'/' ;search below (/) switch ?
If ne Jmp Path_Specified?
;
; If we find this character we want to know if its the first character of the
; command line or not.
;
Cmp DI,Offset Sub_Dir ; have we stored any characters yet?
Jne SB_Not_First_Char
;
; If it is the first we set a flag to keep us from defaulting to the
; root directory before we search
;
Mov RootFlag,1 ; signal to search below, not reset to
Jmp Short Parse_Command_Line ; root
;
; Now, if its not the first character on the command line we need to
; do some fancy footwork. First we need to see if a specific path
; has previously been signaled.
;
SB_Not_First_Char:
Cmp CDFlag,1 ; have we already seen a specific
; path on the command line?
Jne SB_No_Path_Yet ; no so go on
;
; A specific path has been previously selected so we make this path an
; asciiz string and switch to it. Upon completion we reset DI to the
; begining of our command line buffer and clear the specific subdir flag.
;
Mov B [DI],0 ; make current path asciiz string
Call SetPath ; change to the already specified path
;
; If the carry flag is set there was an error in the path (usually it didn't
; exist)
;
Jnc SB_Not_First_Char_Done ; if the subdir doesn't exist leave
Mov Errlvl,5 ; signal error type (invalid path)
Jmp ExitCL ; leave
;
; If the path existed then we reset DI to the beginning of our buffer,
; reset CDFlag and set RootFlag.
;
SB_Not_First_Char_Done:
Mov DI,Offset Sub_Dir ; reset DI
Mov CDFlag,0 ; clear specific subdir flag
Mov RootFlag,1 ; search below, don't default to root
Jmp Short Parse_Command_Line ; go get next char
;
; It hasn't so this means that we search the disk for the subdir specified
; up till now (on the command line). To do this we must make the name an
; asciiz string, search for it then specify that we don't want to default
; to the root directory before out next search. DI must also be reset.
; In doing the search we imitate the CD command by first searching the current
; level and then enhance it by searching the whole disk (if RootFlag set,
; otherwise search only below current dir)
;
SB_No_Path_Yet:
Mov B [DI],0 ; make current path asciiz string
Mov Count,DI ; how many characters stored?
Sub Count,Offset Sub_Dir ; we need to set this for GetDir
;
; Set OneDeepFlag so we only check current directory
;
Mov OneDeepFlag,1 ; start by searching current level
Call GetDir ; search for path already specified
;
; Reset OneDeepFlag, check to see if we are done and if so move on
;
Mov OneDeepFlag,0 ; reset the OneDeepFlag
Cmp Done_Flag,1 ; see if we were successful
Je Search_A_Success ; if not leave
;
; ..otherwise re-search. We reset to the root directory if RootFlag is set
;
Cmp RootFlag,1 ; searching only below?
If ne Call No_Arg ; set to root for search
Mov Count,DI ; how many characters stored?
Sub Count,Offset Sub_Dir ; we need to set this for GetDir
Call GetDir ; search for path already specified
;
; If Done_Flag is set then we have found our directory, otherwise we set
; the carry flag and leave
;
Cmp Done_Flag,1 ; see if we were successful
Je Search_A_Success ; if not leave
Stc
Mov Errlvl,6 ; signal error type (subdir not found)
Jmp ExitCL
;
; We found the subdir, now reset Done_Flag for future use as well as DI
;
Search_A_Success:
Mov Done_Flag,0 ; reset Done_Flag incase of future searches
Mov RootFlag,1 ; search below, don't default to root
Mov DI,Offset Sub_Dir ; reset DI
Jmp Short Parse_Command_Line
;
; The \ switch indicates a specific path is specified. (i.e. no searching
; just switch to this path.
;
Path_Specified?:
Cmp AL,'\' ; Path seperator/indicator (\) ?
If ne Jmp Process_Character
;
; If we find this flag we want to know if its the first character of the
; command line or not.
;
Cmp DI,Offset Sub_Dir ; still pointing to beginning?
Jne PS_Not_First_Char
;
; If it is the first we set a flag to indicate a specific subdir has been
; selected.
;
Change_Dir RootDir ; make sure we are at the root dir
Mov CDFlag,1 ; set flag to select specific subdir
;
; Strip any leading blanks.....
;
P1:
ES Cmp B [SI],' ' ; strip any blanks
Jne P2
Inc SI
Jmp Short P1
;
; If all that's left is a carriage return we are done, otherwise get the next.
;
P2:
ES Cmp B [SI],CR
If ne Jmp Short Parse_Command_Line
Mov Done_Flag,1
Jmp ExitCL
;
; If its not the first character we check to see if another one has already
; been found.
;
PS_Not_First_Char:
Cmp CDFlag,1 ; already set to look for path?
Je Already_Reading_Path ; yes so go on
;
; None has been found yet so we make the current string (in the buffer)
; an asciiz string and go search for the subdir it specifies. After
; the search we reset DI, Done_Flag and CDFlag.
;
Mov B [DI],0 ; make string asciiz
;
; Set the character count and a flag to search the current level
;
Mov Count,DI ; how many characters stored?
Sub Count,Offset Sub_Dir ; we need to set this for GetDir
Mov OneDeepFlag,1 ; start by searching current level
Call GetDir ; search for path already specified
;
; Reset the OneDeepFlag and see if we found our subdir
;
Mov OneDeepFlag,0 ; reset the OneDeepFlag
Cmp Done_Flag,1 ; see if we were successful
Je PS_Search_A_Success ; if not leave
;
; If we didn't find the dir we check to see if we reset to the root and
; continue on with the search.
;
Cmp RootFlag,1 ; reseting to root ?
If ne Call No_Arg ; set to root for search if flag not set
Mov Count,DI ; how many characters stored?
Sub Count,Offset Sub_Dir ; we need to set this for GetDir
Call GetDir ; search for specified path
;
; We have searched the desired part of the drive, now did we find anything?
;
Cmp Done_Flag,1 ; see if we were successful
;
; If we did we reset the flags and continue on, otherwise leave.
;
Je PS_Search_A_Success ; if not leave
Stc ; set carry flag to signal error
Mov Errlvl,6 ; signal error type (subdir not found)
Jmp Short ExitCL
PS_Search_A_Success:
Mov Done_Flag,0 ; reset Done_Flag incase of future searches
Mov DI,Offset Sub_Dir ; reset DI
Mov CDFlag,1 ; indicate specific path
Jmp Short Parse_Command_Line
;
; If we have already seen a path seperator we continue building the
; desired path in our buffer.
;
Already_Reading_Path:
Push ES ; change segment registers. This is
Mov ES,CS ; required if we are enqueued to CED
Stosb
Pop ES
Jmp Short Parse_Command_Line ; and get next char
;
; Now we make sure the character is upper case because DOS doesn't like
; lower case. There is potential for error here because these checks will
; pass some invalid characters (for DOS filenames). The result is some
; delay before an error is found.
;
Process_Character:
Cmp AL,'!' ; compare with !
If b Jmp Parse_Command_Line ; get next char if smaller
Cmp AL,'z' ; compare with z
If a Jmp Parse_Command_Line ; get next char if bigger
Cmp AL,'a' ; lowercase letter?
Jb Store_The_Character ; nope so go on
Xor AL,020 ; make upper case
;
; Now we have an upper case character let's store it in our buffer and
; go get the next
;
Store_The_Character:
Push ES ; again, we have to change the segment
Mov ES,CS ; registers to allow for CED
Stosb
Pop ES
Jmp Short Parse_Command_Line
;
; When we get here we're done with the command line and we must make
; sure that we have an asciiz name in our buffer.
;
We_Are_Finished:
Mov Count,DI ; how many characters stored?
Sub Count,Offset Sub_Dir
;
; If count is zero we have not found anything on the command line so let's
; reset to the root directory and leave
;
Cmp Count,0
Jne Something_In_Buffer
;
; Show the path
;
Call ShowPath ; display the path
Mov Done_Flag,1 ; signal done
Jmp Short ExitCL ; leave
;
; We found something so let's make sure its an asciiz string
;
Something_In_Buffer:
Mov AL,0
Push ES ; override the segment registers
Mov ES,CS
Stosb
Pop ES
Jmp Short ExitCL
;
; If an illegal drive was specified on the command line we come here and
; display and error message. The Done_Flag is then set and we return to
; the main program.
;
DriveError: ; we come here if the drive specifier
; is not in A to z
Pop DI
Mov Errlvl,1
Stc
ExitCL:
Ret
;---------------------------------------------------------------------------;
; GetDir ;
; ;
; GetDir searches for the desired subdirectory. The extent of the ;
; search can be modified by command line switches ;
; ;
; Based on WHISK by Charles Wooster ;
;---------------------------------------------------------------------------;
GetDir:
Push SI,DI,ES
Mov ES,CS
Mov Done_Flag,0
; Find first or next subdirectory level
; -------------------------------------
NextLevel:
Mov DX,[DTAPointer] ; Next nested DTA
Mov AH,1Ah ; For DOS call to set DTA
Int 21h ; Do it
Cmp [Direction],0 ; Check if we're nesting
Jnz FindNextFile ; If not, we're continuing
Mov DX,Offset SearchAsciiZ ; We search for *.*
Mov CX,10h ; Subdirectory attribute
Mov AH,4Eh ; Find first file
Int 21h ; by calling DOS
Jmp Short TestMatch ; Hop around next section
FindNextFile:
Mov AH,4Fh ; Find next file
Int 21h ; by calling DOS
TestMatch:
Jc NoMoreFiles ; If CY flag, at end of rope
Mov BX,[DTAPointer] ; Our find stuff is here
Test B [BX + 21],10h ; Test if directory attribute
Jz FindNextFile ; If not, continue search
Add BX,30 ; Now points to directory name
Cmp Byte Ptr [BX],'.' ; Ignore "." and ".." entries
Jz FindNextFile ; by continuing the search
Cmp OneDeepFlag,1 ; looking only at this level?
Je Compare
Push BX ; save pointer to subdir name
Mov DX,BX ; Now DX points to found dir
Mov AH,3Bh ; Set up DOS function call
Int 21h ; And change directory
Pop BX ; get pointer to subdir name back
Compare:
Sub CX,CX
Mov CX,Count
Mov DI, Offset Sub_Dir
Lea SI, BX
Repe Cmpsb
Jz Found ; matched up so leave
Cmp OneDeepFlag,1
Jne GoOn
Mov [Direction],-1
Jmp Short NextLevel
GoOn:
Add [DtaPointer],43 ; New DTA for new level
Mov [Direction],0 ; I.E., Find first file
Jmp NextLevel ; All ready to cycle through
; No More Files Found -- go back to previous level
; ------------------------------------------------
NoMoreFiles:
Cmp [DTAPointer],Offset DtaAreaBegin ; See if back at start
Jz ExitGD ; If so, that's all, folks
Sub [DTAPointer],43 ; Back one for previous
Mov [Direction],-1 ; I.E., will find next file
Mov DX,Offset BackOneDir ; The string ".."
Mov AH,3Bh ; Call to change directory
Int 21h ; Change directory to father
Jmp NextLevel ; And continue the search
Found:
Cmp OneDeepFlag,1
If ne Jmp Short F1
Mov DX,BX ; Now DX points to found dir
Mov AH,3Bh ; Set up DOS function call
Int 21h ; And change directory
F1:
Mov Done_Flag,1
ExitGD:
Mov [Direction],0
Pop ES,DI,SI
Ret
;---------------------------------------------------------------------------;
; SetPath ;
;